/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物体.h"


#include "面/intern/网格.h"
#include "面/面.h"
#include "面/几何模型生成.h"

#include "intern/模型/S_模型.h"
#include "intern/粒子系统.h"
#include "intern/expand/FBX模型加载保存.h"
#include "intern/expand/OBJ模型加载保存.h"
#include "intern/灯光.h"



#include <文件/file_载入保存数据.h>
#include <matXX.h>


static std::map<std::wstring, S_物体*> g物体表;

static void f_ob_分配变换矩阵(S_物体* ob, S_设备环境& ctx) {
	switch (ob->m_Type) {
	case E_物体类型::t_多边形:
	case E_物体类型::t_网格:
	case E_物体类型::t_灯光:
	case E_物体类型::t_包:
	case E_物体类型::t_线:
	case E_物体类型::t_线段:
	case E_物体类型::t_骨架:
	case E_物体类型::t_物体包: {
		f_ob_创建矩阵(ob, ctx);
		break;
	}
	default:
		break;
	}
}

S_物体* f_ob_创建物体(E_物体类型 type, S_物体* froObj, S_设备环境 ctx) {
	S_物体* ob = 0;
	switch (ctx.m_Type) {
	case E_Vulkan: {
			switch (type) {
				case E_物体类型::t_网格: {
					ob = f_ob_创建物体(ctx, E_物体类型::t_网格);
					ob->f_setDataNum(1);
					ob->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN));
					//========================= 创建和初始化物体矩阵数据 ===========================
					f_ob_创建矩阵(ob, ctx);
					break;
				}

				case E_物体类型::t_多边形: {
					ob = f_ob_创建物体(ctx, E_物体类型::t_多边形);
					
					ob->m_UserData = f_surface_copy((S_多边形*)froObj->m_UserData);
					//ob->f_setData(f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN));
					//========================= 创建和初始化物体矩阵数据 ===========================
					f_ob_创建矩阵(ob, ctx);
					break;
				}
				
				case E_物体类型::t_摄像机: {
					auto* 像机 = f_创建摄像机(ctx);
					//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
					ob = 像机;
					break;
				}
				
				case E_物体类型::t_粒子: {
					auto p = new S_粒子系统(froObj);
					p->m_粒子 = f_create粒子系统(100, ctx);
					ob = p;
					break;
				}
				
				case E_物体类型::t_骨骼: {
					ob = f_ob_创建骨骼(froObj);
					break;
				}
				case E_物体类型::t_骨架: {
					ob = new S_物体(type);
					if (froObj) {
						if (froObj->m_变换矩阵.m_Mem.m_大小) {
							f_ob_创建矩阵(ob, ctx);
						}
						//f_ob_创建矩阵(ob, ctx);
					}
					break;
				}
				case E_物体类型::t_物体包: {
					ob = new S_物体(type);
					if (froObj) {
						//f_ob_创建矩阵(ob, ctx);
						if (froObj->m_变换矩阵.m_Mem.m_大小) {
							f_ob_创建矩阵(ob, ctx);
						}
					}
					break;
				}

				case E_物体类型::t_空: {
					ob = new S_物体(E_物体类型::t_空);
					S_GL立即模式;
				}
				break;

				case E_物体类型::t_实例: {
					ob = f_ob_创建物体实例(froObj, 0);
				}
				break;

			default:
				break;
			}
			if (froObj) {
				f_ob_set数据槽数量(ob, froObj->m_DataNum);
			}
			
		}
		break;
	case E_CUDA:
		switch (type)
		{
			case E_物体类型::t_网格: {
				auto* 模型 = new S_模型();
				模型->m_网格 = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_CUDA);
				//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
				ob = 模型;
			}
			break;

			case E_物体类型::t_摄像机: {
				auto* 像机 = new S_摄像机(ctx);
				//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
				ob = 像机;
			}
			break;

			case E_物体类型::t_灯光: {
				auto* 灯光 = new S_物体(E_物体类型::t_灯光);
				//模型->m_网格->m_板载缓存 = f_构建网格板载内存(ctx);
				ob = 灯光;
			}
			break;

			case E_物体类型::t_粒子: {
				auto p = new S_粒子系统(froObj);
				p->m_粒子 = f_create粒子系统(100, ctx);
				ob = p;
			}
			break;

		default:
			break;
		}
		break;
	case E_DirectX12:
		ob = new S_物体(type);
		break;
	default:
		break;
	}

	return ob;
}

S_物体* f_ob_创建物体(S_设备环境& ctx, E_物体类型 type) {
	S_物体* ob = nullptr;
	switch (type) {
		case E_物体类型::t_摄像机: {
			ob = f_创建摄像机(ctx);
		}
	}
	if (ob) return ob;

	ob = new S_物体(type);

	switch (type) {
		case E_物体类型::t_实例:
			ob->m_是否实例 = true;
			break;
		
		case E_物体类型::t_骨架:
			ob->m_独立缩放 = f_buf_create板载缓存(ctx, sizeof(S_单色材质属性), E_板载缓存类型::e_UBO);
			f_buf_fill板载缓存<S_单色材质属性>(ob->m_独立缩放, { {0,1,0} }, E_板载缓存类型::e_UBO);

			f_ob_set数据槽数量(ob, 1);
			f_ob_set数据(ob, f_ob_创建骨架());
		
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格:
		case E_物体类型::t_灯光:
		case E_物体类型::t_线:
		case E_物体类型::t_线段:
		case E_物体类型::t_物体包: {
			f_ob_创建矩阵(ob, ctx);
		}
		break;
		
		case E_物体类型::t_包:
			f_ob_创建矩阵(ob, ctx, 1);
			break;
		case E_物体类型::t_粒子: {
			break;
		}
		
		case E_物体类型::t_骨骼: {
			break;
		}

		case E_物体类型::t_虚拟体:
		case E_物体类型::t_点光源:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_平行光:
		case E_物体类型::t_区域光_方形:
		case E_物体类型::t_区域光_圆形:
		case E_物体类型::t_区域光: {
			ob->m_是否实例 = true;
			break;
		}
		break;

	}

	return ob;
}

S_物体* f_ob_创建物体实例(S_物体* 父物体, uint32 loc) {
	//S_物体* ob = new S_物体(froObj->m_Type);
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;
	ob->m_父物体 = 父物体;
	return ob;
}

S_物体* f_ob_创建物体实例(S_物体* froObj) {
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;
	ob->m_实例ID = froObj->m_子物体.size();
	froObj->m_子物体.push_back(ob);
	return ob;
}

S_物体* f_ob_添加实例(S_物体* 父物体, uint32 实例ID) {
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;

	if (实例ID == -1) {
		ob->m_实例ID = 父物体->m_子物体.size();
	}
	else {
		ob->m_实例ID = 实例ID;
	}

	f_ob_添加矩阵(父物体, ob->m_实例ID);
	父物体->m_子物体.push_back(ob);
	return ob;
}

S_物体* f_ob_创建骨骼(S_物体* 父物体) {
	S_物体* ob = new S_物体(E_物体类型::t_骨骼);
	f_ob_set数据槽数量(ob, 1);

	S_骨骼* 骨骼 = (S_骨骼*)malloc(sizeof(S_骨骼));
	骨骼->m_长度 = 1.0;
	骨骼->m_旋转 = vec4{0,0,0,1};
	f_ob_set数据(ob, 骨骼);
	
	return ob;
}

//S_物体* f_ob_创建骨骼(S_设备环境& ctx) {
//	S_物体* ob = new S_物体(E_物体类型::t_骨骼);
//	f_ob_创建矩阵(ob, ctx);
//	return ob;
//}

S_物体* f_ob_创建灯光(S_设备环境& ctx, E_物体类型 type) {
	void* data = nullptr;
	switch (type) {
	case E_物体类型::t_平行光: {
		data = f_ob_calloc平行光();
		break;
	}
	case E_物体类型::t_聚光灯: {
		data = f_ob_calloc聚光灯();
		break;
	}
	case E_物体类型::t_点光源: {
		data = f_ob_calloc点光源();
		break;
	}
	case E_物体类型::t_区域光: {
		data = f_ob_calloc区域光();
		break;
	}
	
	default:
		return nullptr;
	}



	S_物体* ob = new S_物体(type);

	S_灯光场景数据* 灯光场景数据 = f_ob_calloc灯光场景数据();
	灯光场景数据->m_灯光 = ob;

	f_ob_set数据槽数量(ob, 2);
	f_ob_set数据(ob, data);
	f_ob_set数据(ob, 灯光场景数据, 1);
	f_ob_创建矩阵(ob, ctx);
	return ob;
}

void f_ob_销毁物体(S_物体* ob) {
	switch (ob->m_Type) {
	case E_物体类型::t_网格: {
		break;
	}
	case E_物体类型::t_多边形: {
		//f_surface_销毁多边形((S_多边形*)ob->m_UserData);
		break;
	}
	}
	delete ob;
}

void f_ob_改变物体类型(S_物体* ob, E_物体类型 新类型, S_设备环境& ctx) {
	switch (ob->m_Type) {
	case E_物体类型::t_网格: {
		switch (新类型) {
		case E_物体类型::t_实例:
			ob->m_是否实例 = true;
			ob->f_setDataNum(0);
			break;
		}

		if (!ob->m_变换矩阵.m_Mem.m_大小) {
			f_ob_添加矩阵(ob);
		}
		break;
	}

	case E_物体类型::t_实例: {
		switch (新类型) {
		case E_物体类型::t_网格:
			if (ob->m_变换矩阵.m_Buf) {
				//f_buf_gresize(ob->m_变换矩阵, 1);
				f_ob_添加矩阵(ob);
			}
			else {
				f_ob_创建矩阵(ob, ctx);
			}
			ob->m_是否实例 = false;
			break;
		}
		break;
	}

	case E_物体类型::t_摄像机: {
		break;
	}

	case E_物体类型::t_粒子: {
		break;
	}
	
	case E_物体类型::t_骨骼: {
		break;
	}

	case E_物体类型::t_骨架: {
		break;
	}

	case E_物体类型::t_物体包: {
		break;
	}

	case E_物体类型::t_GL立即模式: {
		break;
	}

	case E_物体类型::t_空: {
		break;
	}

	default:
		break;
	}

	ob->m_Type = 新类型;

}






S_物体* f_创建BOX物体(const vec3& size, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建物体(E_物体类型::t_网格, 0, ctx);
	auto* mesh = f_ob_fromMesh(obj);

	vec3 hafl = size / 2;

	std::vector<vec3> p(8);
	p[0] = { -hafl.x, -hafl.y, -hafl.z };
	p[1] = { -hafl.x, hafl.y, -hafl.z };
	p[2] = { hafl.x, hafl.y, -hafl.z };
	p[3] = { hafl.x, -hafl.y, -hafl.z };

	p[4] = { -hafl.x, -hafl.y, hafl.z };
	p[5] = { -hafl.x, hafl.y, hafl.z };
	p[6] = { hafl.x, hafl.y, hafl.z };
	p[7] = { hafl.x, -hafl.y, hafl.z };

	
	std::vector<uint32> index(36);
	if (三角化) {
		index[0] = 0; index[1] = 1; index[2] = 2;
		index[3] = 3; index[4] = 1; index[5] = 2;

		index[6] = 3; index[7] = 2; index[8] = 6;
		index[9] = 3; index[10] = 6; index[11] = 7;

		index[12] = 2; index[13] = 1; index[14] = 5;
		index[15] = 2; index[16] = 5; index[17] = 6;

		index[18] = 1; index[19] = 0; index[20] = 5;
		index[21] = 5; index[22] = 0; index[23] = 4;

		index[24] = 0; index[25] = 3; index[26] = 7;
		index[27] = 3; index[28] = 7; index[29] = 4;

		index[30] = 5; index[31] = 4; index[32] = 6;
		index[33] = 4; index[34] = 7; index[35] = 6;
	}
	
	mesh->f_fill顶点(p.data(), p.size());
	mesh->f_fill法线(p);
	f_surface_fill索引数据(mesh, index);

	return obj;
}

S_物体* f_创建圆柱物体(const vec3& 高_半径, uint32 细分, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建物体(E_物体类型::t_网格, 0, ctx);
	auto* mesh = f_ob_fromMesh(obj);

	std::vector<vec3> p(细分*2);
	f_构建圆柱(高_半径.x, { 高_半径.y, 高_半径.z }, 细分, p.data());
	p.push_back({ -高_半径.x * 0.5f, 0.0f, 0.0f });
	p.push_back({ 高_半径.x * 0.5f, 0.0f, 0.0f});

	std::vector<uint32> index(细分*12);
	for (uint32 i = 0; i < 细分; ++i) {
		if (i) {
			index[i*6] = p.size() - 2;
			index[i*6 + 1] = i - 1;
			index[i * 6 + 2] = i;

			index[i * 6 + 3] = p.size() - 1;
			index[i * 6 + 4] = 细分 + i - 1;
			index[i * 6 + 5] = 细分 + i;


			index[细分 * 6 + i * 6    ] = 细分 + i - 1;
			index[细分 * 6 + i * 6 + 1] = i-1;
			index[细分 * 6 + i * 6 + 2] = i;
			index[细分 * 6 + i * 6 + 3] = 细分 + i - 1;
			index[细分 * 6 + i * 6 + 4] = i;
			index[细分 * 6 + i * 6 + 5] = 细分 + i;
		}
		else {
			index[0] = p.size() - 2;
			index[1] = 0;
			index[2] = 细分-1;

			index[3] = p.size() - 1;
			index[4] = 细分 * 2 - 1;
			index[5] = 细分;


			index[细分 * 6 + 0] = 细分*2 - 1;
			index[细分 * 6 + 1] = 细分 - 1;
			index[细分 * 6 + 2] = 0;
			index[细分 * 6 + 3] = 细分*2 - 1;
			index[细分 * 6 + 4] = 0;
			index[细分 * 6 + 5] = 细分;
		}

		/*index[细分 * 6 + i*6 + 0] = 细分 * 2 + i - 1;
		index[细分 * 6 + i*6 + 1] = 细分 + i - 1;
		index[细分 * 6 + i*6 + 2] = i;
		index[细分 * 6 + i*6 + 3] = 细分 * 2 - 1;
		index[细分 * 6 + i*6 + 4] = 细分 + i;
		index[细分 * 6 + i*6 + 5] = 细分 * 2 + i;*/
	}

	mesh->f_fill顶点(p.data(), p.size());
	mesh->f_fill法线(p);
	f_surface_fill索引数据(mesh, index);

	return obj;
}

S_物体* f_创建球体物体(const float32 半径, uvec2 细分, S_设备环境 ctx, bool 三角化, E_绘图API engineType) {
	auto* obj = f_ob_创建物体(E_物体类型::t_网格, 0, ctx);
	auto* mesh = f_ob_fromMesh(obj);

	uint32 经度细分 = 细分.x;
	uint32 维度细分 = 细分.y;
	if (经度细分 < 3) 经度细分 = 3;
	if (维度细分 < 3) 维度细分 = 3;


	std::vector<vec3> 顶点(经度细分 * 维度细分 + 2);
	std::vector<vec3> 法线(经度细分 * 维度细分 + 2);



	float32* p顶点 = (float32*)&顶点[0];

	顶点[0].x = 0.0;
	顶点[0].y = -半径;
	顶点[0].x = 0.0;

	vec3_填充(&法线[0], 0.0, -1.0, 0.0);



	S_Tranform 变换;
	f_TranformInit(变换);
	矩阵_创建缩放矩阵v(缩放矩阵, (float32*)&变换.scale);

	//float32 坐标X[3] = { -半径, 0.0, 0.0 };
	float32	Normal[4] = { 0.0, -1.0, 0.0, 1.0 };
	vec4	NewNormal = { 0.0, 1.0, 0.0, 0.0 };
	float32	坐标Z[4] = { 0.0, -半径, 0.0, 1.0 };
	float32	原点坐标[4] = { 0.0, 0.0, 0.0 , 0.0 };
	矩阵_创建移动矩阵v(移动矩阵, 坐标Z);
	for (uint16 纬度 = 0; 纬度 < 维度细分; ++纬度) {
		float32 当前维度 = (180.0 / (float32)维度细分) * (float32)(纬度 + 1);

		矩阵_创建X旋转矩阵(X旋转矩阵, 当前维度);
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 id = 纬度 * 经度细分 + 经度 + 1;

			float32 当前经度 = (360.0 / (float32)经度细分) * (float32)(经度);

			float32 RY[3] = { 当前维度, 当前经度, 0.0 };
			矩阵_创建Y旋转矩阵(Y旋转矩阵, 当前经度);
			矩阵_创建单位矩阵4X4(变换矩阵);
			
			Mat4X4_相乘(&变换矩阵, &Y旋转矩阵);
			Mat4X4_相乘(&变换矩阵, &X旋转矩阵);


			vec3_填充(原点坐标, 0.0);
			vec4_填充(&NewNormal, 0.0);
			MAT变换坐标4(&变换矩阵, 坐标Z, 原点坐标);
			MAT变换坐标4(&变换矩阵, Normal, &NewNormal);
			顶点[id].x = 原点坐标[0];
			顶点[id].y = 原点坐标[1];
			顶点[id].z = 原点坐标[2];

			vec3_填充(&法线[id], &NewNormal);
		}
	}

	顶点[经度细分 * 维度细分 + 1].x = 0.0;
	顶点[经度细分 * 维度细分 + 1].y = 半径;
	顶点[经度细分 * 维度细分 + 1].x = 0.0;
	mesh->f_fill顶点(顶点.data(), 顶点.size());
	//f_填充顶点数据(mesh, 顶点);
	

	vec3_填充(&法线[经度细分 * 维度细分 + 1], 0.0, 1.0, 0.0);
	mesh->f_fill法线(法线);
	//f_填充法线数据(mesh, 法线);
	


	std::vector<uint32> 索引(顶点.size() * 6);

	//底部盖
	索引[0] = 0;
	uint32 V1 = 0;
	uint32 V2 = 1;
	uint32 V3 = 2;
	uint32 V4 = 0;
	uint32 index = 0;
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {

		索引[index + 0] = 0;
		索引[index + 1] = V2;
		索引[index + 2] = V3;

		index += 3;

		V2 += 1; if (V2 >= 经度细分 + 2) V2 = 1;
		V3 += 1; if (V3 >= 经度细分 + 2) V3 = 2;
	}
	索引[index - 2] = 0;

	//================== 中间 ====================
	for (uint16 纬度 = 0; 纬度 < 维度细分 - 2; ++纬度) {
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 idL1 = 纬度 * 经度细分 + 经度 + 2;
			uint16 idL2 = (纬度 + 1) * 经度细分 + 经度 + 2;


			V1 = idL1; V2 = idL2; V3 = idL1 + 1; V4 = idL2 + 1;

			if (uint32(经度 + 1) >= 经度细分) V3 = 纬度 * 经度细分 + 2;
			if (uint32(经度 + 1) >= 经度细分) V4 = (纬度 + 1) * 经度细分 + 2;


			索引[index + 0] = V1;
			索引[index + 1] = V2;
			索引[index + 2] = V3;
			index += 3;

			索引[index + 0] = V3;
			索引[index + 1] = V2;
			索引[index + 2] = V4;
			index += 3;

		}
	}

	//
	V1 = 经度细分 * 维度细分 + 1;

	//顶部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		uint16 idL1 = (维度细分 - 2) * 经度细分 + 经度 + 2;
		V2 = idL1; V3 = idL1 + 1;
		if (uint32(经度 + 1) >= 经度细分) V3 = (维度细分 - 2) * 经度细分 + 2;

		索引[index + 0] = V2;
		索引[index + 1] = V1;
		索引[index + 2] = V3;

		index += 3;
	}
	索引[index - 1] = 经度细分 * 维度细分 + 1;

	
	f_surface_fill索引数据(mesh, 索引);
	//f_填充索引数据(mesh, 索引);
	//mesh->f_填充绘制间隔(vector<ui2_32>({ { 0, uint32(索引.size()) } }));

	return obj;
}

void f_ob_create骨骼虚拟体网格(S_设备环境& ctx, S_物体* 骨骼, S_物体* 骨节) {
	vec2 size = { 1.0f, 0.1f };
	DEF_3Fs V;
	DEF_3Fs N;
	DEF_Is I;
	DEF_2Fs uv;



	auto* 骨骼mesh = f_ob_fromMesh(骨骼);
	if (!骨骼mesh) {
		骨骼->f_setDataNum(1);
		骨骼mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
		骨骼->f_setData(骨骼mesh, 0);

		f_mesh_set绘制属性(骨骼mesh, {});
	}

	f_graph_构建骨骼锥体(size, V, N, I);
	f_surface_fill顶点数据(骨骼mesh, V);
	f_surface_fill索引数据(骨骼mesh, I);
	f_surface_计算包围盒(骨骼mesh);

	骨骼mesh->m_线宽 = 3.0;
	骨骼mesh->m_深度控制 = { 0.0001f, 0.0f };



	if (骨节) {
		auto* 骨节mesh = f_ob_fromMesh(骨节);
		if (!骨节mesh) {
			骨节->f_setDataNum(1);
			骨节mesh = f_surface_创建网格对象(nullptr, ctx, E_网格数据枚举::e_Mesh_VULKAN);
			骨节->f_setData(骨节mesh, 0);
		}
		f_graph_构建球体(32, 16, size.y*0.5, V, N, uv, I);
		f_surface_fill顶点数据(骨节mesh, V);
		f_surface_fill索引数据(骨节mesh, I);
		f_surface_计算包围盒(骨节mesh);

		骨节mesh->m_线宽 = 3.0;
		骨节mesh->m_深度控制 = { 0.0001f, 0.0f };

		f_mesh_set绘制属性(骨节mesh, {});
	}
}


void f_ob_构建骨骼虚拟体实例ID(S_物体* ob, uint32& d) {
	ob->m_实例ID = d;
	++d;
	for (auto& e : ob->m_子物体) {
		f_ob_构建骨骼虚拟体实例ID(e, d);
	}
	if (!ob->m_实例ID) f_ob_set实例数量(ob, d);
}

static void f_ob_递归绑定子骨头骨骼对象(S_物体* ob, S_骨架* 骨骼, uint32& d) {
	if (ob->m_Type == E_物体类型::t_骨骼) {
		ob->m_骨架 = 骨骼;
		ob->m_实例ID = d;
		++d;
	}
	for (auto& e : ob->m_子物体) {
		f_ob_递归绑定子骨头骨骼对象(e, 骨骼, d);
	}
}

void f_ob_构建骨骼(S_物体* ob, S_物体* 骨骼物体, S_物体* 骨节物体, S_物体* 骨骼辅助虚拟物体) {
	S_骨架* 骨架 = f_ob_from骨架(ob);

	C_骨骼管理::m_骨骼容器.insert(骨架);
	uint32 num = 0;
	f_ob_递归绑定子骨头骨骼对象(ob, 骨架, num);

	f_buf_gresize(骨架->m_骨骼长度, num);
	f_buf_gresize(骨架->m_骨骼变换, num);
	f_buf_gresize(骨架->m_初始姿态, num);
	f_buf_gresize(骨架->m_变换姿态, num);


	
	骨架->m_骨头数量 = num;
	f_ob_fill实例(骨骼物体, num);

	num += ob->m_子物体.size();
	f_ob_fill实例(骨节物体, num);

}

void f_ob_绑定网格骨骼(S_物体* ob, S_物体* bonse, uint32 mesh_loc) {
	if (mesh_loc < ob->m_DataNum) {
		(S_Mesh*)ob->m_Data[mesh_loc];

		ob->m_骨架 = bonse->m_骨架;
	}
}







S_摄像机* f_创建摄像机(S_设备环境 ctx, E_绘图API engineType) {
	S_摄像机* camera = new S_摄像机(ctx);

	//camera->m_变换矩阵.m_MemOffset = f_buf_galloc(S_物体::g_变换矩阵[ctx.m_逻辑设备.ID], 3);
	//camera->m_变换矩阵.m_Buf = S_物体::g_变换矩阵[ctx.m_逻辑设备.ID];
	camera->m_投影矩阵 = f_buf_create板载缓存(ctx, sizeof(Mat44f), E_板载缓存类型::e_UBO);
	
	camera->f_LookAt({ 0.0f, 0.0f, -10.0f }, { 0.0f,0.0f,0.0f }, { 0.0f,1.0f,0.0f });
	camera->f_set透视投影(45.0f, 1.0f, {0.01f, 2000.0f});

	return camera;
}

void f_ob_销毁摄像机(S_摄像机* camera) {
	//f_buf_gfree(camera->m_变换矩阵.m_Buf, camera->m_变换矩阵.m_MemOffset);
	f_buf_release板载缓存(camera->m_投影矩阵);
	delete camera;
}



void f_ob_link物体数据(S_物体* ob, S_物体* froObj) {
	f_ob_set数据槽数量(ob, froObj->m_DataNum);
	
	for (uint16 i = 0; i < ob->m_DataNum; ++i) {
		ob->m_Data[i] = froObj->m_Data[i];
		switch (ob->m_Type) {
			case E_物体类型::t_线:
			case E_物体类型::t_线段:
			case E_物体类型::t_网格:
			case E_物体类型::t_多边形:
				f_ob_set材质(ob, ((S_Mesh*)ob->m_Data[i])->m_Material, i);
				break;
		default:
			break;
		}
	}
}

S_物体* f_ob_copy物体数据(S_设备环境& ctx, S_物体* froObj) {
	S_物体* ob = f_ob_创建物体(froObj->m_Type, froObj, ctx);
	
	ob->m_变换 = froObj->m_变换;
	
	if (froObj->m_位置) ob->m_位置 = f_an_拷贝曲线通道(froObj->m_位置);
	if (froObj->m_旋转) ob->m_旋转 = f_an_拷贝曲线通道(froObj->m_旋转);
	if (froObj->m_缩放) ob->m_缩放 = f_an_拷贝曲线通道(froObj->m_缩放);


	ob->m_实例ID = froObj->m_实例ID;
	ob->m_是否实例 = froObj->m_是否实例;

	if (froObj->m_UserData) {
		switch (froObj->m_Type)
		{
		case E_物体类型::t_骨骼: {
			S_物体* 骨节 = f_ob_copy物体数据(ctx, (S_物体*)froObj->m_UserData);
			ob->m_UserData = 骨节;
			break;
		}
		default:
			break;
		}
	}

	f_ob_link物体数据(ob, froObj);
	f_ob_set实例数量(ob, ob->m_变换矩阵.m_Mem.m_大小);
	

	for (auto& e : froObj->m_子物体) {
		auto* 新子物体 = f_ob_copy物体数据(ctx, e);
		f_ob_add子物体(ob, 新子物体);
	}

	return ob;
}

void f_ob_set数据槽数量(S_物体* Obj, uint32 num) {
	for (uint32 i = num; i < Obj->m_DataNum; ++i) {
		f_buf_erase(Obj->m_实例颜色[i]);
	}

	Obj->m_实例颜色.resize(num);
	for (uint32 i = 0; i < num; ++i) {
		Obj->m_实例颜色[i] = f_buf_alloc(S_物体::g_物体颜色[i], 1);
	}

	if (Obj->m_DataNum != num) {
		Obj->f_setDataNum(num);
	}
	
}

void f_ob_set数据(S_物体* Obj, void* data, uint8 loc) {
	Obj->f_setData(data, loc);
}

void f_ob_set实例数量(S_物体* Ob, uint32 num, uint32 deviceID)  {
	Ob->m_是否实例 = false;
	Ob->m_子物体.resize(num);
	//if (!num) return;

	uint32 offset = Ob->m_变换矩阵.m_Mem.m_大小;
	f_buf_gresize(Ob->m_变换矩阵, num);

	for (uint32 i = 0; i < Ob->m_DataNum; ++i) {
		auto* mesh = f_ob_fromMesh(Ob, i);
		if (mesh && mesh->m_颜色) {
			f_buf_resize(mesh->m_颜色, num);
		}

		f_buf_gresize(Ob->m_实例颜色[i], num);
	}
	if (num > 1) Ob->m_根实例 = true;
}

void f_ob_fill实例(S_物体* Ob, uint32 num) {
	uint32 已有数量 = Ob->m_子物体.size();

	for (uint32 i = num; i < 已有数量; ++i) {
		delete Ob->m_子物体[i];
	}
	f_ob_set实例数量(Ob, num);

	for (uint32 i = 已有数量; i < num; ++i) {
		Ob->m_子物体[i] = new S_物体(E_物体类型::t_实例);
		Ob->m_子物体[i]->m_父物体 = Ob;
	}
}

void f_ob_set为实例(S_物体* Obj) {
	Obj->m_是否实例 = true;
	//Obj->m_Type = E_物体类型::t_实例;
	Obj->m_DataNum = 0;
	if(Obj->m_Data) free(Obj->m_Data);
	Obj->m_Data = nullptr;
}

void f_ob_set物体数据可视(S_物体* Obj, uint8 loc, bool 是否可视)  {
	((S_Mesh*)(Obj->m_Data[loc]))->m_显示 = 是否可视;
}

/*void f_ob_重置顶点数量(S_物体* Obj, uint32 num) {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	f_buf_gresize(m_顶点, num);
	f_buf_resize(((S_VKMesh板载缓存*)mesh->m_网格)->m_顶点, num, E_板载缓存类型::e_VBO);
}*/

void f_ob_set线宽(S_物体* Obj, float32 h, uint8 loc)  {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	if (mesh) {
		mesh->m_线宽 = h;
	}
	else if (Obj->m_DataNum) {
		((S_Mesh*)(Obj->m_Data[loc]))->m_线宽 = h;
	}
}

void f_ob_set细分(S_物体* Obj, uint32 次数, uint8 loc)  {
	//if (Obj->m_GPU参数布局[loc].m_参数数量 >= 3) {
	//	uvec3 dim = { 次数 ,次数 ,次数 };
	//	f_buf_fill板载缓存<uvec3>(Obj->m_GPU参数布局[loc].m_参数槽[2], &dim, 1, E_板载缓存类型::e_UBO);
	//}
}

void f_ob_set网格可视(S_物体* ob, bool show, uint8 loc) {
	((S_Mesh*)(ob->m_Data[loc]))->m_显示 = show;
}

void f_ob_set材质(S_物体* Obj, S_材质* mat, uint8 loc)  {
	switch (Obj->m_Type)
	{
	//case E_物体类型::t_虚拟体:
	case E_物体类型::t_骨架:
	case E_物体类型::t_包:
	case E_物体类型::t_线:
	case E_物体类型::t_线段:
	case E_物体类型::t_灯光:
	case E_物体类型::t_网格:
	case E_物体类型::t_多边形: {
	assert(loc < Obj->m_DataNum);
		if (Obj->m_DataNum) {
			auto mesh = (S_Mesh*)(Obj->m_Data[loc]);
			mesh->m_Material = mat;
			if (mesh->m_Material->mf_GPU参数配置) {
				mesh->m_Material->mf_GPU参数配置(mesh->m_Material, Obj, mesh, loc);
			}
			else {
				mesh->m_Material->mf_GPU材质槽更新(mesh->m_Material, mesh->m_GPU参数布局, 2);
			}
		}
		else {
			auto mesh = f_ob_fromMesh(Obj);
			auto model = dynamic_cast<S_模型*>(Obj);

			if (model) {
				model->m_网格->m_Material = mat;
			}
		}
		break;
	}
		
	case E_物体类型::t_粒子: {
		auto* psys = dynamic_cast<S_粒子系统*>(Obj);
		psys->m_粒子->m_Material = mat;
		mat->m_Shader->f_alloc参数设置(&(psys->m_粒子->m_Material->m_GPU参数set));

		break;
	}
	
	default:
		break;
	}

	Obj->m_isUpdate = true;
	Obj->m_UpdateGPU参数布局 = true;

}

void f_ob_set矩阵(S_物体* Obj, C_Mat44& mat) {
	f_buf_Mat44_at(Obj->m_变换矩阵, Obj->m_实例ID) = *((Mat44f*)(mat.columns));
	Obj->m_isUpdateMatrix = true;
}

void f_ob_set矩阵(S_物体* Obj, const Mat44f& mat, uint32 实例ID) {
	if (Obj->m_变换矩阵.m_Mem.m_大小 > 实例ID) {
		f_buf_Mat44_at(Obj->m_变换矩阵, 实例ID) = mat;
	}
	else if(Obj->m_父物体) {
		f_ob_set矩阵(Obj->m_父物体, mat, 实例ID);
	}
	Obj->m_isUpdateMatrix = true;
}

void f_ob_set颜色2(S_物体* Obj, S_RGBA8UI color, uint32 offset, uint8 槽) {
	if (Obj->m_是否实例) {
		if (Obj->m_父物体 && Obj->m_父物体->m_是否实例) {
			f_ob_set颜色2(Obj->m_父物体, color, offset, 槽);
			return;
		}
		offset = Obj->m_实例ID;
		Obj = Obj->m_父物体;
	}
	assert(Obj->m_实例颜色.size() > 槽);
	f_buf_UI32_at(Obj->m_实例颜色[槽], offset) = f_PackData4X8(color);
}

void f_set粒子数量(S_物体* Obj, uint32 num) {
	auto psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		f_set粒子数量(psys->m_粒子, num);
	}
}

void f_set粒子位置(S_物体* Obj, const vec3* l, uint32 num) {
	auto psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		f_set粒子位置(psys->m_粒子, l, num);
	}
}

void f_set粒子速度(S_物体* Obj, const vec3* v, uint32 num)
{
}

void f_set粒子旋转(S_物体* Obj, const vec3* r, uint32 num)
{
}

void f_set粒子大小(S_物体* Obj, const vec3* s, uint32 num)
{
}

void f_set粒子渲染物体(S_物体* Obj, E_粒子绘制类型 绘制类型) {
	S_粒子系统* psys = dynamic_cast<S_粒子系统*>(Obj);
	if (psys) {
		psys->m_粒子;
	}
}

void f_ob_set颜色(S_物体* Obj, const S_RGBA8UI& color, uint32 槽) {
	(S_Mesh*)(Obj->m_Data[槽]);
	f_surface_fill颜色((S_Mesh*)(Obj->m_Data[槽]), color, 0, -1);
}

S_物体* f_ob_copy(S_设备环境& ctx, S_物体* Obj, bool 链接) {
	S_物体* newObj = f_ob_创建物体(ctx, Obj->m_Type);
	if (链接) {
		f_ob_link物体数据(newObj, Obj);

		newObj->m_UserData = Obj->m_UserData;
	}
	else {
		newObj->m_变换 = Obj->m_变换;

		if (Obj->m_位置) newObj->m_位置 = f_an_拷贝曲线通道(Obj->m_位置);
		if (Obj->m_旋转) newObj->m_旋转 = f_an_拷贝曲线通道(Obj->m_旋转);
		if (Obj->m_缩放) newObj->m_缩放 = f_an_拷贝曲线通道(Obj->m_缩放);

		//f_ob_set矩阵(newObj, f_mat44_构建XYZ变换矩阵(newObj->m_变换), 0);

		switch (Obj->m_Type) {
		case E_物体类型::t_多边形: {
			newObj->m_UserData = f_surface_copy((S_多边形*)Obj->m_UserData);
			break;
		}
		default:
			break;
		}
	}

	newObj->m_实例ID = Obj->m_实例ID;
	newObj->m_是否实例 = Obj->m_是否实例;


	for (auto& e : Obj->m_子物体) {
		auto* 新子物体 = f_ob_copy(ctx, e, 链接);
		f_ob_add子物体(newObj, 新子物体);
	}

	return newObj;
}

void* f_ob_copyData(S_物体* 目标物体, S_物体* 源物体, bool 链接) {
	
	return nullptr;
}

/*void f_ob_创建实例Data(S_物体* Obj, void* data, uint8 loc) {
	switch (Obj->m_Type) {
	case E_物体类型::t_网格:
		if (Obj->m_Data[loc] == nullptr) {
			//Obj->m_Data[loc] = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
		}
		//f_surface_创建实例(Obj->m_Data[loc], (S_Mesh*)data);
		break;
	}
}*/


S_Mesh* f_ob_fromTranformMesh(S_物体* froObj, uint32 loc) {
	S_Mesh* mesh = nullptr;
	switch (froObj->m_Type) {
	case E_物体类型::t_网格:
	case E_物体类型::t_多边形:
		if (froObj->m_Data) {
			mesh = f_surface_创建网格对象(E_网格数据枚举::e_Mesh_CPU);
			f_surface_Copy(mesh, (S_Mesh*)(froObj->m_Data[loc]));
			f_surface_变换(mesh, froObj->m_变换);
		}
		break;
	default:
		break;
	}
	
	return mesh;
}

S_LigthParallel* f_ob_fromParallelLigth(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_平行光) {
		return (S_LigthParallel*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LigthSpot* f_ob_fromLigthSpot(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_聚光灯) {
		return (S_LigthSpot*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LigthPoint* f_ob_fromLigthPoint(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_点光源) {
		return (S_LigthPoint*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_LigthArea* f_ob_fromAreaLigth(S_物体* froObj) {
	if (froObj->m_Type == E_物体类型::t_区域光) {
		return (S_LigthArea*)(froObj->m_Data[0]);
	}
	assert(0);
	return nullptr;
}

S_灯光场景数据* f_ob_fromLigthSceneData(S_物体* froObj) {
	switch (froObj->m_Type) {
	case E_物体类型::t_平行光:
	case E_物体类型::t_聚光灯:
	case E_物体类型::t_点光源:
	case E_物体类型::t_区域光:
		return (S_灯光场景数据*)(froObj->m_Data[1]);
	default:
		break;
	}
	return nullptr;
}

uint32 f_ob_get实例数量(S_物体* ob) {
	//S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	return ob->m_变换矩阵.m_Mem.m_大小;
}

uint32 f_ob_get顶点数量(S_物体* Obj) {
	S_模型* mesh = dynamic_cast<S_模型*>(Obj);
	return mesh->m_网格->f_get顶点数量();
}

float32 f_ob_get最大半径(S_物体* Obj) {

	return float32();
}

S_VecSphere f_ob_get范围(S_物体* Obj) {

	return S_VecSphere();
}

S_物体* f_ob_get子对象(S_物体* Obj, uint32 offset) {
	if (offset >= Obj->m_子物体.size()) {
		return nullptr;
		return Obj->m_子物体.back();
	}
	return Obj->m_子物体[offset];
}

S_物体* f_ob_get实例ID对象(S_物体* Obj, uint32 ID) {
	uint32 num = Obj->m_子物体.size();
	auto* obs = Obj->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		if (obs[i]->m_实例ID == ID) {
			return obs[i];
		}
	}

	for (uint32 i = 0; i < num; ++i) {
		S_物体* ob = f_ob_get实例ID对象(obs[i], ID);
		if (ob) return ob;
	}
	return nullptr;
}

S_物体* f_ob_get父变换对象(S_物体* Obj) {
	if (Obj->m_父物体) {
		if (Obj->m_父物体->m_变换矩阵.m_Mem.m_大小) {
			return Obj->m_父物体;
		}
		else {
			return f_ob_get父变换对象(Obj->m_父物体);
		}
	}
	return nullptr;
}

vec3 f_ob_get全局坐标(S_物体* Obj, uint32 ID) {
	if (Obj->m_变换矩阵.m_Mem.m_大小) {
		return f_buf_Mat44_at(Obj->m_变换矩阵, ID) * vec3{ 0,0,0 };
	}
	else {
		if (Obj->m_父物体) {
			return f_ob_get全局坐标(Obj->m_父物体, ID);
		}
	}
	return Obj->f_get位置();
}

Mat44f f_ob_get变换矩阵(S_物体* ob) {
	ob = f_ob_from实例对象取父对象(ob);
	Mat44f mat;
	if (ob->m_变换矩阵.m_Mem.m_大小) {
		return f_buf_Mat44_at(ob->m_变换矩阵, ob->m_实例ID);
	}
	else {
		mat = f_mat44_identity();
	}
	return mat;
}

//Mat44f f_ob_get实例变换矩阵(S_物体* Ob, uint32 ID) {
//	if (ID < Ob->m_变换矩阵.m_Mem.m_大小) f_buf_Mat44_at(Ob->m_变换矩阵, ID);
//	return f_buf_Mat44_at(Ob->m_变换矩阵, 0);
//}


S_物体* f_ob_from实例对象取父对象(S_物体* Obj) {
	switch (Obj->m_Type) {
	case E_物体类型::t_实例:
	case E_物体类型::t_骨架:
	case E_物体类型::t_骨骼:
	case E_物体类型::t_虚拟体:
		return f_ob_from实例对象取父对象(Obj->m_父物体);
	default:
		break;
	}
	return Obj;
}

E_物体类型 f_ob_get可视对象类型(S_物体* Obj) {
	//if (f_ob_fromMesh(Obj)) {
	//	return Obj->m_Type;
	//}

	switch (Obj->m_Type)
	{
	//case E_物体类型::t_骨架:
	//case E_物体类型::t_骨骼:
	case E_物体类型::t_物体包: {
		if(Obj->m_子物体.size()) return f_ob_get可视对象类型(Obj->m_子物体.front());
	}
	default:
		break;
	}

	return Obj->m_Type;
}

uint64 f_ob_get子物体数量(S_物体* Ob, bool 包括子集) {
	return Ob->m_子物体.size();
}

S_物体* f_ob_以类型查找子物体(S_物体* ob, E_物体类型 type) {
	if(ob->m_Type == type) return ob;
	uint32 num = ob->m_子物体.size();
	S_物体** data = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		S_物体* findOb = f_ob_以类型查找子物体(data[i], type);
		if (findOb) {
			return findOb;
		}
	}
	return nullptr;
}




uint32 f_ob_add子物体(S_物体* 父, S_物体* 子, uint32 loc) {
	if (父) {
		if (loc >= 父->m_子物体.size()) {
			loc = 父->m_子物体.size();
			父->m_子物体.push_back(子);
		}
		else {
			父->m_子物体[loc] = 子;
		}

		子->m_父物体 = 父;
		父->m_isUpdate = true;

		switch (子->m_Type) {
		case E_物体类型::t_区域光:
		case E_物体类型::t_点光源:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_平行光:
		case E_物体类型::t_虚拟体:
			子->m_实例ID = loc;
			break;
		default:
			break;
		}
	}
	return loc;
}

void f_ob_add实例物体(S_物体* 父, S_物体* 子物体, uint32 loc) {
	子物体->m_实例ID = 父->m_子物体.size();

	f_ob_add子物体(父, 子物体, loc);

	if (父->m_变换矩阵.m_Mem.m_大小 < 父->m_子物体.size()) {
		f_ob_添加矩阵(父);
	}
	子物体->m_是否实例 = true;
}

void f_ob_ins实例物体(S_物体* 父, uint32 实例ID, uint32 loc) {
	S_物体* ob = nullptr;
	if (loc >= 父->m_子物体.size()) {
		ob = f_ob_创建物体实例(父, loc);
		f_ob_add子物体(父, ob, loc);
	}
	ob->m_实例ID = 实例ID;
}

void f_ob_set实例物体(S_物体* 父, S_物体* 子, uint32 loc) {
	父->m_子物体[loc] = 子;
	子->m_实例ID = loc;
	子->m_父物体 = 父;
}

void f_ob_clear子物体(S_物体* 父, uint64 s, uint64 e) {
	uint32 num = 父->m_子物体.size();
	if (!num) return;
	if (e > num) {
		e = num;
	}

	auto iter_s = 父->m_子物体.begin() + s;
	auto iter_e = 父->m_子物体.begin() + e;
	
	父->m_子物体.erase(iter_s, iter_e);
}

void f_ob_销毁子物体(S_物体* 父, uint64 s, uint64 e) {
	uint32 num = 父->m_子物体.size();
	if (!num) return;
	if (e > num) {
		e = num;
	}


	f_ob_删除矩阵(父, s, e - s);
	for (uint32 i = s; i < e; ++i) {
		f_ob_销毁物体(父->m_子物体[i]);
	}

	auto iter_s = 父->m_子物体.begin() + s;
	auto iter_e = 父->m_子物体.begin() + e;

	父->m_子物体.erase(iter_s, iter_e);
	num = 父->m_子物体.size();
	for (uint32 i = s; i < num; ++i) {
		父->m_子物体[i]->m_实例ID = i;
	}
}

void f_ob_setPos(S_物体* ob, const vec3& loc, uint32 id) {
	ob->f_set位置(loc, id);
}

void f_ob_Load物体(S_物体* ob, FILE* f) {
	ob->m_Name = f_file_读取字符串(f);
	fread(&ob->m_Type, sizeof(E_物体类型), 1, f);

	std::vector<vec3> 变换(3);
	file_读取序列到文件(f, &变换);
	ob->m_变换.location = 变换[0];
	ob->m_变换.rotation = 变换[1];
	ob->m_变换.scale = 变换[2];


	ob->m_位置 = f_an_Load通道(f);
	ob->m_旋转 = f_an_Load通道(f);
	ob->m_缩放 = f_an_Load通道(f);

	if(ob->m_位置) ob->m_位置->ObPtr = ob;
	if(ob->m_旋转) ob->m_旋转->ObPtr = ob;
	if(ob->m_缩放) ob->m_缩放->ObPtr = ob;
}

void f_ob_Save物体(S_物体* ob, FILE* f) {
	f_file_保存字符串(f, ob->m_Name);
	fwrite(&ob->m_Type, sizeof(E_物体类型), 1, f);

	std::vector<vec3> 变换;
	变换.push_back(ob->m_变换.location);
	变换.push_back(ob->m_变换.rotation);
	变换.push_back(ob->m_变换.scale);
	file_写入序列到文件(f, 变换);


	f_an_Save通道(ob->m_位置, f);
	f_an_Save通道(ob->m_旋转, f);
	f_an_Save通道(ob->m_缩放, f);
}




const uint8* f_ob_Load物体(S_物体* ob, const uint8* 块) {
	块 = f_解宽字符串(ob->m_Name, 块);
	块 = f_文件块_取数据块(ob->m_Type, 块);


	块 = f_文件块_取数据块(ob->m_变换.location, 块);
	块 = f_文件块_取数据块(ob->m_变换.rotation, 块);
	块 = f_文件块_取数据块(ob->m_变换.scale, 块);


	块 = f_an_Load通道(&ob->m_位置, 块);
	块 = f_an_Load通道(&ob->m_旋转, 块);
	块 = f_an_Load通道(&ob->m_缩放, 块);
	

	if (ob->m_位置) ob->m_位置->ObPtr = ob;
	if (ob->m_旋转) ob->m_旋转->ObPtr = ob;
	if (ob->m_缩放) ob->m_缩放->ObPtr = ob;

	return 块;
}

void f_ob_Save物体(S_物体* ob, S_UI8Array* 块) {
	f_包宽字符串(块, ob->m_Name);
	f_core_array_push_back_block((S_Array*)块, (uint8*)&ob->m_Type, sizeof(uint32));
	

	f_文件块_写数据块(块, ob->m_变换.location);
	f_文件块_写数据块(块, ob->m_变换.rotation);
	f_文件块_写数据块(块, ob->m_变换.scale);
	

	f_an_Save通道(ob->m_位置, 块);
	f_an_Save通道(ob->m_旋转, 块);
	f_an_Save通道(ob->m_缩放, 块);
}


const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块) {
	uint32 num = 0;
	块 = f_文件块_取数据块(num, 块);

	for (uint32 i = 0; i < num; ++i) {
		块 = f_ob_Load物体(obs->ptr_userData[i], 块);
	}
	return 块;
}

void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块) {
	f_文件块_写数据块(块, obs->count);

	for (uint32 i = 0; i < obs->count; ++i) {
		f_ob_Save物体(obs->ptr_userData[i], 块);
	}
}


void f_ob_Load多物体(S_OBArray* objs, FILE* f, S_设备环境& ctx, bool 数据) {
	uint32 num;
	fread(&num, sizeof(uint32), 1, f);
	f_core_array_resize((S_Array*)objs, num);
	
	for (uint32 i = 0; i < num; ++i) {
		S_物体* ob = new S_物体(E_物体类型::t_空);
		f_ob_Load物体(ob, f);
		f_ob_分配变换矩阵(ob, ctx);
		objs->ptr_userData[i] = ob;


		switch (objs->ptr_userData[i]->m_Type) {
		case E_物体类型::t_多边形:
			objs->ptr_userData[i]->m_UserData = f_surface_多边形加载(f);
			break;
		case E_物体类型::t_网格: {
			int32 数据槽数量 = 0;
			fread(&数据槽数量, sizeof(uint32), 1, f);

			f_ob_set数据槽数量(ob, 数据槽数量);
			for (uint32 j = 0; j < 数据槽数量; ++j) {
				auto* mesh = f_ob_fromMesh(objs->ptr_userData[i], j);
			}
			break;
		}
		default:
			break;
		}
	}
}

void f_ob_Save多物体(const S_OBArray* objs, FILE* f, bool 数据) {
	fwrite(&objs->count, sizeof(uint32), 1, f);

	for (uint32 i = 0; i < objs->count; ++i) {
		f_ob_Save物体(objs->ptr_userData[i], f);


		switch (objs->ptr_userData[i]->m_Type) {
		case E_物体类型::t_多边形:
			f_surface_多边形保存(f, (S_多边形*)objs->ptr_userData[i]->m_UserData);
			break;
		case E_物体类型::t_网格: {
			//fwrite(&(mesh->m_是否链接), sizeof(bool), 1, f);
			//if(mesh->m_是否链接) f_save网格(f, mesh);

			int32 num = objs->ptr_userData[i]->m_DataNum;
			if (数据 && num) {
				fwrite(&num, sizeof(int32), 1, f);

				for (uint32 j = 0; j < num; ++j) {
					auto* mesh = f_ob_fromMesh(objs->ptr_userData[i], j);
				}
			}
			else {
				num = 0;
				fwrite(&num, sizeof(int32), 1, f);
			}
			break;
		}

		default:
			break;
		}
	}
}



void f_load物体(FILE* f, S_物体* obj) {
	obj->m_Name = f_file_读取字符串(f);
	
	auto mat = f_创建BL右手转GL右手坐标系();

	auto matR = f_构建旋转矩阵(90.0, E_轴向::e_X);
	auto matRA = f_构建旋转矩阵(-90.0, E_轴向::e_X);
	auto matS = f_构建缩放矩阵(vec3{ 1.0, -1.0, 1.0 });
	mat = matS * matR;

	std::vector<vec3> 变换(3);
	f_读取文件(f, &变换);
	变换[1].x = -变换[1].x;
	变换[1].y = -变换[1].y;
	变换[1].z = -变换[1].z;
	
	obj->m_变换.location = 变换[0];
	obj->m_变换.rotation = 变换[1];
	obj->m_变换.scale = 变换[2];

	switch (obj->m_Type) {
	case E_物体类型::t_网格:
	case E_物体类型::t_多边形:
		f_load网格(f, dynamic_cast<S_模型*>(obj)->m_网格, DEF_Vert预设_vn);
		break;
	default:
		break;
	}
	
}

void f_save物体(FILE* f, S_物体* obj) {
	f_file_保存字符串(f, obj->m_Name);
	

	std::vector<vec3> 变换;
	变换.push_back(obj->m_变换.location);
	变换.push_back(obj->m_变换.rotation);
	变换.push_back(obj->m_变换.scale);
	f_写入文件(f, 变换);

	switch (obj->m_Type) {
	case E_物体类型::t_网格:
	case E_物体类型::t_多边形:
		f_save网格(f, dynamic_cast<S_模型*>(obj)->m_网格);
		break;
	default:
		break;
	}
}

std::vector<S_物体*> f_load多物体(FILE* f, S_设备环境 ctx) {
	uint32 num = 0;
	fread(&num, sizeof(uint32), 1, f);
	
	std::vector<S_物体*> data(num);
	if (!num) data;

	for (uint32 i = 0; i < num; ++i) {
		uint32 type = 0;
		file_单数值读取(f, type);

		data[i] = f_ob_创建物体(E_物体类型(type), 0, ctx);
		f_load物体(f, data[i]);
		if (ctx.m_Type == E_绘图API::E_Vulkan) {

		}
		else {
			
		}
		
	}
	
	return data;
}

void f_save多物体(FILE* f, const std::vector<S_物体*>& objs) {
	uint32 num = uint32(objs.size());
	auto* obj = objs.data();
	for (uint32 i = 0; i < num; ++i) {
		file_单数值保存(f, obj[i]->m_Type);

		f_save物体(f, obj[i]);
	}

}

void f_ob_loadFBX(std::vector<S_物体*>& objs, std::string& path, S_设备环境& ctx) {
	f_Ex加载FBX模型(objs, path, ctx);
	return;
}

S_物体* f_ob_loadOBJ(const std::string& path, S_设备环境 ctx) {
	S_物体* ob = f_Ex加载OBJ模型(path, ctx);
	return ob;
}















vec3 f_obj_get方向(S_物体* obj, E_轴向 轴向) {
	C_Mat44 mat = C_Mat44::kIdentity;

	auto rx = f_构建旋转矩阵(obj->m_变换.rotation.x, E_轴向::e_X);
	auto ry = f_构建旋转矩阵(obj->m_变换.rotation.y, E_轴向::e_Y);
	auto rz = f_构建旋转矩阵(obj->m_变换.rotation.z, E_轴向::e_Z);

	mat *= rz;
	mat *= ry;
	mat *= rx;

	mat = f_逆矩阵(mat);


	vec3 dir;
	switch (轴向) {
	case E_轴向::e_X:
		dir = mat * vec3{ 1.0f, 0.0f, 0.0f };
	case E_轴向::e_Y:
		dir = mat * vec3{ 0.0f, 1.0f, 0.0f };
	case E_轴向::e_Z:
		dir = mat * vec3{ 0.0f, 0.0f, 1.0f };
	default:
		break;
	}

	return vec_normalize2(dir);
}

vec3 f_ob_get中心(const std::vector<S_物体*>& obs) {
	vec3 中心坐标 = {};
	uint32 num = 0;

	for (auto& ob : obs) {
		vec_add(&中心坐标, f_ob_get全局坐标(ob, ob->m_实例ID));
		++num;
	}

	if(num) return 中心坐标 / num;
	return {};
}

void f_ob_增量移动(S_物体* obj, vec3 距离) {
	switch (obj->m_Type) {
	case E_物体类型::t_摄像机: {
		auto* came = dynamic_cast<S_摄像机*>(obj);
		vec_add(&came->m_眼睛偏移, 距离);
		came->m_isUpdate = true;
	}
		
		break;
	case E_物体类型::t_网格:

		break;
	default:
		break;
	}
}

void f_ob_set缩放(S_物体* obj, const vec3& 缩放) {
	obj->f_set缩放(缩放, obj->m_实例ID);
}

float32 f_get相机到视点距离(S_摄像机* camera) {
	return fabs(camera->m_视点距离);
	return vec_len(camera->f_get位置() - camera->m_视点);
}

vec3 f_camera_get视线向量(S_摄像机* camera) {
	auto rx = RotationMatrix(M_角度转弧度(camera->m_变换.rotation.x), { 1.0f,0.0f,0.0f });
	auto ry = RotationMatrix(M_角度转弧度(camera->m_变换.rotation.y), { 0.0f,1.0f,0.0f });
	//auto ry = RotationMatrix(M_角度转弧度(-camera->m_变换.rotation.y), { 0.0f,1.0f,0.0f });
	auto sel = ScaleMatrix({ camera->m_缩放.x, camera->m_缩放.y, camera->m_缩放.z });

	//vec3 dir = f_逆矩阵(ry * rx * sel) * vec3 { 0, 0, -1, };
	vec3 dir = f_逆矩阵((rx * ry) * sel) * vec3{ 0, 0, -1, };
	//return { -dir.x, -dir.y, -dir.z };
	return dir;
}

vec3 f_camera_计算摄像机以角度缩放大小(S_摄像机* camera) {
	vec3 scale = { 1, 1.0f / camera->m_宽高比, float32(tan(M_角度转弧度(180 - camera->m_视角) * 0.5)) };
	return scale;
}

vec3 f_camera_get眼睛位置(S_摄像机* camera) {
	return (f_逆矩阵(*(Mat44*)&camera->m_相机位置矩阵) * vec3 { 0, 0, 0 });
}

vec3 f_get相机变换后位置(S_摄像机* camera) {
	//auto 逆矩阵 = f_求逆矩阵(camera->m_相机位置矩阵);
	//return 逆矩阵 * vec3{ 0.0f, 0.0f, camera->m_视点距离 };
	return f_逆矩阵(*(Mat44*)&camera->m_相机位置矩阵) * vec3{ 0.0f, 0.0f, -camera->m_视点距离 } - camera->m_眼睛偏移;
	//f_mat44_Inverse()
	auto mat = f_构建移动矩阵({ 0.0f, 0.0f, -camera->m_视点距离 });
	auto rx = RotationMatrix(M_角度转弧度(-camera->m_变换.rotation.x), { 1.0f,0.0f,0.0f });
	auto ry = RotationMatrix(M_角度转弧度(-camera->m_变换.rotation.y), { 0.0f,1.0f,0.0f });
	auto s = ScaleMatrix({ 1.0f,1.0f,1.0f });

	auto offset = f_构建移动矩阵({ -camera->m_眼睛偏移.x, -camera->m_眼睛偏移.y, -camera->m_眼睛偏移.z });

	vec3 v = mat * offset * (rx * ry) * s * vec3{ 0.0f, 0.0f, camera->m_视点距离 };

	return v;
}

void f_set摄像机视点位置(S_摄像机* camera, vec3 pos) {
	camera->m_isUpdate = true;

	vec3 眼睛位置 = f_camera_get眼睛位置(camera);
	vec3 视点 = f_camera_get视线向量(camera) * camera->m_视点距离;
	视点 = 眼睛位置 + 视点;

	//视点 = pos + 视点;
	视点 = pos + camera->m_视点;
	camera->m_视点 = vec_反向(pos);
	camera->m_眼睛偏移 = {};
}

void f_set摄像机视点移动到偏移点(S_摄像机* camera) {
	//camera->m_视点.x += 0.2;
	camera->m_isUpdate = true;

	auto rx = RotationMatrix(M_角度转弧度(camera->m_变换.rotation.x), { 1.0f,0.0f,0.0f });
	auto ry = RotationMatrix(M_角度转弧度(-camera->m_变换.rotation.y), { 0.0f,1.0f,0.0f });

	vec3 方向 = ry * rx * vec3{ 0, 0, 1 };
	auto 相机位置 = (f_逆矩阵(*(Mat44*)&camera->m_相机位置矩阵) * vec3 { 0, 0, 0 });
	
	camera->m_眼睛偏移 = {};
	camera->m_视点 = 相机位置 + 方向 * camera->m_视点距离;
	camera->m_视点 = vec_反向(camera->m_视点);
	return;

}

void f_camera_set偏移视点(S_摄像机* camera, const vec3& pos) {
	vec3 视线 = f_camera_get视线向量(camera);
	vec3 眼睛位置 = f_camera_get眼睛位置(camera);
	vec3 斜边 = pos - 眼睛位置;
	float32 斜边长度 = vec_normalize(&斜边);

	
	if (camera->m_投影模式 == E_投影模式::e_透视) {
		//camera->m_视点距离 = -f_graph_三角函数_斜边计算临边长度(斜边长度, f_graph_两向量夹角弧度(斜边, 视线));
	}
	vec3 视点 = 眼睛位置 - (视线 * camera->m_视点距离);
	

	auto rotMat = f_camera_计算旋转矩阵(*camera, false);
	camera->m_眼睛偏移 = rotMat * (pos - 视点);
	camera->m_视点 = vec_反向(pos);

}

vec3 f_camera_get相机视线平移方向(const S_摄像机& camera, vec3& H, vec3& V) {
	auto rx = RotationMatrix(M_角度转弧度(camera.m_变换.rotation.x), { 1.0f,0.0f,0.0f });
	auto ry = RotationMatrix(M_角度转弧度(camera.m_变换.rotation.y), { 0.0f,1.0f,0.0f });
	auto sel = ScaleMatrix({ camera.m_缩放.x, camera.m_缩放.y, camera.m_缩放.z });

	auto mat = f_逆矩阵((rx * ry) * sel);
	H = vec_normalize2(mat * vec3{ 1, 0, 0 });
	V = vec_normalize2(mat * vec3{ 0, 1, 0 });

	return H + V;
}

//vec3 f_camera_get视线向量(S_摄像机* camera) {
//	return vec_normalize2((camera->m_相机位置矩阵) * vec3 { 0, 0, 1 });
//}

void f_ob_set域(S_物体* Obj, S_DomProp& 域绘制参数, uint8 loc) {
	//if (Obj->m_GPU参数布局[loc].m_参数数量 >= 3) {
	//	S_DomProp 绘制参数;
	//	f_buf_fill板载缓存<S_DomProp>(Obj->m_GPU参数布局[loc].m_参数槽[2], &域绘制参数, 1, E_板载缓存类型::e_UBO);
	//}
}





















